home *** CD-ROM | disk | FTP | other *** search
/ Technotools / Technotools (Chestnut CD-ROM)(1993).ISO / lantools / lanrmote / slave.asm < prev    next >
Assembly Source File  |  1990-04-21  |  20KB  |  688 lines

  1.  
  2. ;----------------------------------------------------
  3. ;
  4. ;       SLAVE -- allow another PC (on a Netbios LAN)
  5. ;       to control this one.  (see MASTER.ASM)
  6. ;
  7. ;       Test version 0.9
  8. ;
  9. ;       (c) 1990 Barry Nance
  10. ;
  11. ;----------------------------------------------------
  12.  
  13.                 DOSSEG
  14.                 .MODEL small
  15.  
  16. StdIn           =       0000
  17. StdOut          =       0001
  18. StdErr          =       0002
  19.  
  20. RESET                   =       032h
  21. CANCEL                  =       035h
  22. STATUS                  =       0b3h
  23. STATUS_WAIT             =       033h
  24. TRACE                   =       0f9h
  25. TRACE_WAIT              =       079h
  26. UNLINK                  =       070h
  27. ADD_NAME                =       0b0h
  28. ADD_NAME_WAIT           =       030h
  29. ADD_GROUP_NAME          =       0b6h
  30. ADD_GROUP_NAME_WAIT     =       036h
  31. DELETE_NAME             =       0b1h
  32. DELETE_NAME_WAIT        =       031h
  33. CALL_CMD                =       090h
  34. CALL_WAIT               =       010h
  35. LISTEN                  =       091h
  36. LISTEN_WAIT             =       011h
  37. HANG_UP                 =       092h
  38. HANG_UP_WAIT            =       012h
  39. SEND                    =       094h
  40. SEND_WAIT               =       014h
  41. SEND_NO_ACK             =       0f1h
  42. SEND_NO_ACK_WAIT        =       071h
  43. CHAIN_SEND              =       097h
  44. CHAIN_SEND_WAIT         =       017h
  45. CHAIN_SEND_NO_ACK       =       0f2h
  46. CHAIN_SEND_NO_ACK_WAIT  =       072h
  47. RECEIVE                 =       095h
  48. RECEIVE_WAIT            =       015h
  49. RECEIVE_ANY             =       096h
  50. RECEIVE_ANY_WAIT        =       016h
  51. SESSION_STATUS          =       0b4h
  52. SESSION_STATUS_WAIT     =       034h
  53. SEND_DATAGRAM           =       0a0h
  54. SEND_DATAGRAM_WAIT      =       020h
  55. SEND_BCST_DATAGRAM      =       0a2h
  56. SEND_BCST_DATAGRAM_WAIT =       022h
  57. RECEIVE_DATAGRAM        =       0a1h
  58. RECEIVE_DATAGRAM_WAIT   =       021h
  59. RECEIVE_BCST_DATAGRAM   =       0a3h
  60. RECEIVE_BCST_DATAGRAM_WAIT =    023h
  61.  
  62. NCB             struc
  63.     COMMAND     db      ?
  64.     RETCODE     db      ?
  65.     LSN         db      ?
  66.     NUM         db      ?
  67.     BUFFER_PTR  dd      ?
  68.     LEN         dw      ?
  69.     CALLNAME    db      16 dup (?)
  70.     OURNAME     db      16 dup (?)
  71.     RTO         db      ?
  72.     STO         db      ?
  73.     POST_FUNC   dd      ?
  74.     LANA_NUM    db      ?
  75.     CMD_CPLT    db      ?
  76.     RESERVE     db      14 dup (?)
  77. NCB             EndS
  78.  
  79.                 .DATA
  80. EGAFlagPtr      Label   DWord
  81. EGAFlagOfs      DW      0487h
  82. EGAFlagSeg      DW      0
  83.  
  84. Msg1            DB      "SLAVE is now waiting for MASTER to make contact."
  85.                 DB      13, 10
  86. Msg1Len         =       $-Msg1
  87.  
  88. Msg2            DB      "Early versions of DOS not supported."
  89.                 DB      13, 10
  90. Msg2Len         =       $-Msg2
  91.  
  92. Msg3            DB      "Error--NETBIOS not active."
  93.                 DB      13, 10
  94. Msg3Len         =       $-Msg3
  95.  
  96. Msg4            DB      "Adding name to network..."
  97.                 DB      13, 10
  98. Msg4Len         =       $-Msg4
  99.  
  100.                 .STACK 200h
  101.                 .CODE
  102.  
  103. ;---------------------------------------
  104.  
  105. our_psp         DW      0
  106. our_mcb_seg     DW      0
  107. next_mcb_seg    DW      0
  108. dos_major       DB      0
  109. dos_minor       DB      0
  110. SessionActive   DB      0
  111. OurNameNumber   DB      0
  112. InInt8          DB      0
  113.  
  114. slave_name      DB      "Slave          "
  115.                 DB      0
  116. master_name     DB      "Master         "
  117.                 DB      0
  118.  
  119. send_ncb        NCB     <>
  120. recv_ncb        NCB     <>
  121. add_name_ncb    NCB     <>
  122. delete_name_ncb NCB     <>
  123.  
  124. oldint08        Label   DWord
  125. oldint08_ofs    DW      0
  126. oldint08_seg    DW      0
  127.  
  128. VideoPtr        Label   DWord
  129. VideoOfs        DW      0
  130. VideoSeg        DW      0
  131. ScreenSave      DB      4000 Dup(0)
  132.  
  133. Screen_Data     Label   Byte
  134.   ScreenPos     DW      0
  135.   CursorShape   DW      0
  136.   CursorLoc     DW      0
  137.   Head2         DW      0
  138.   ScreenPkt     DB      500 Dup(0)
  139.  
  140. Kbd_Data        Label   Byte
  141.   KbdFlag1      DB      0
  142.   KbdFlag2      DB      0
  143.   AltInput      DB      0
  144.   Sess_Flag     DW      0
  145.   Tail          DW      0
  146.   KbdBuffer     DW      16 Dup(0)
  147.  
  148. QuadrantCounter DW      0
  149. Quadrant        DW      8
  150. Quadrant_Ofs    DW      0
  151.  
  152. SS_Save1        DW      0
  153. SP_Save1        DW      0
  154. StackSeg1       DW      0
  155. StackOfs1       DW      0
  156.  
  157.                 DW      256 Dup(0)
  158. OurStack1       DW      0
  159.  
  160. SS_Save2        DW      0
  161. SP_Save2        DW      0
  162. StackSeg2       DW      0
  163. StackOfs2       DW      0
  164.  
  165.                 DW      256 Dup(0)
  166. OurStack2       DW      0
  167.  
  168. ;---------------------------------------
  169.  
  170.                 Assume  CS:_TEXT, DS:_TEXT, ES:Nothing
  171.  
  172. Add_Our_Name    Proc    Near
  173.                 push    ds
  174.  
  175.                 push    cs
  176.                 pop     ds
  177.                 push    cs
  178.                 pop     es
  179.  
  180.                 mov     add_name_ncb.COMMAND, ADD_NAME
  181.                 mov     si, offset slave_name
  182.                 mov     di, offset add_name_ncb.OURNAME
  183.                 mov     cx, 8
  184.         rep     movsw
  185.                 mov     word ptr add_name_ncb.POST_FUNC+2, 0
  186.                 mov     word ptr add_name_ncb.POST_FUNC, 0
  187.                 mov     add_name_ncb.CMD_CPLT, 0FFh
  188.                 mov     bx, offset add_name_ncb
  189.                 Int     5Ch
  190.  
  191. wait_add:       cmp     add_name_ncb.CMD_CPLT, 0FFh
  192.                 je      wait_add
  193.  
  194.                 pop     ds
  195.                 ret
  196. Add_Our_Name    EndP
  197.  
  198.  
  199. ;
  200. ;       enter Send with:
  201. ;       DX:AX - address of buffer
  202. ;       CX    - number of bytes to send
  203. ;       BP:BX - address of POST routine
  204. ;       DS:SI - address of destination name
  205. ;
  206.  
  207. Send_Msg        Proc    Near
  208.                 push    ds
  209.  
  210.                 push    cs
  211.                 pop     ds
  212.                 push    cs
  213.                 pop     es
  214.  
  215.                 mov     send_ncb.COMMAND, SEND_DATAGRAM
  216.                 lea     di, send_ncb.CALLNAME
  217.                 push    ax
  218.                 push    cx
  219.                 mov     cx, 8
  220.         rep     movsw
  221.                 mov     al, OurNameNumber
  222.                 mov     send_ncb.NUM, al
  223.                 pop     cx
  224.                 pop     ax
  225.                 mov     send_ncb.LEN, cx
  226.                 mov     word ptr send_ncb.BUFFER_PTR+2, dx
  227.                 mov     word ptr send_ncb.BUFFER_PTR, ax
  228.                 mov     word ptr send_ncb.POST_FUNC+2, bp
  229.                 mov     word ptr send_ncb.POST_FUNC, bx
  230.                 mov     send_ncb.CMD_CPLT, 0FFh
  231.                 mov     bx, offset send_ncb
  232.                 int     5Ch
  233.  
  234.                 pop     ds
  235.                 ret
  236. Send_Msg        EndP
  237.  
  238.  
  239. Recv_Msg        Proc    Near
  240.                 push    ds
  241.  
  242.                 push    cs
  243.                 pop     ds
  244.                 push    cs
  245.                 pop     es
  246.  
  247.                 push    ax
  248.                 mov     recv_ncb.COMMAND, RECEIVE_DATAGRAM
  249.                 mov     al, OurNameNumber
  250.                 mov     recv_ncb.NUM, al
  251.                 mov     recv_ncb.LEN, cx
  252.                 pop     ax
  253.                 mov     word ptr recv_ncb.BUFFER_PTR+2, dx
  254.                 mov     word ptr recv_ncb.BUFFER_PTR, ax
  255.                 mov     word ptr recv_ncb.POST_FUNC+2, bp
  256.                 mov     word ptr recv_ncb.POST_FUNC, bx
  257.                 mov     recv_ncb.CMD_CPLT, 0FFh
  258.                 mov     bx, offset recv_ncb
  259.                 Int     5Ch
  260.  
  261.                 pop     ds
  262.                 ret
  263. Recv_Msg        EndP
  264.  
  265.  
  266.                 Assume  CS:_TEXT, DS:Nothing, ES:Nothing
  267.  
  268. Int_08:         pushf
  269.                 call    cs:oldint08
  270.  
  271. I8_Sw_Stack1:   mov     cs:SS_Save1, ss
  272.                 mov     cs:SP_Save1, sp
  273.                 mov     ss, cs:StackSeg1
  274.                 mov     sp, cs:StackOfs1
  275.  
  276.                 sti
  277.                 cld
  278.  
  279. I8_save_regs:   push    ax
  280.                 push    bx
  281.                 push    cx
  282.                 push    dx
  283.                 push    si
  284.                 push    di
  285.                 push    bp
  286.                 push    ds
  287.                 push    es
  288.  
  289.                 Assume  CS:_TEXT, DS:_TEXT
  290.                 mov     ax, cs
  291.                 mov     ds, ax
  292.  
  293.                 mov     QuadrantCounter, 0
  294.  
  295. I8_Semaphore:   Cmp     InInt8, 0
  296.                 JE      I8_Sess_Switch
  297.  
  298.                 Jmp     I8_RestoreRegs
  299.  
  300. I8_Sess_Switch: cmp     SessionActive, 1
  301.                 je      I8_ChkHotIRQs
  302.  
  303. br_to_exit:     jmp     Int08Exit
  304.  
  305. I8_ChkHotIRQs:  mov     InInt8, 1
  306.                 Mov     AL, 0bh
  307.                 Out     20h, AL
  308.                 In      AL, 20h
  309.                 Cmp     AL, 0
  310.                 JE      I8_ChkScreen
  311.  
  312.                 Jmp     Int08Exit
  313.  
  314. I8_ChkScreen:   cmp     send_ncb.CMD_CPLT, 0FFh
  315.                 je      br_to_exit
  316.  
  317. Next_Quadrant:  inc     Quadrant
  318.                 add     Quadrant_Ofs, 500
  319.                 cmp     Quadrant, 9
  320.                 jne     ChkThisSection
  321.  
  322.                 mov     Quadrant, 1
  323.                 mov     Quadrant_Ofs, 0
  324.  
  325. ChkThisSection: les     di, VideoPtr
  326.                 mov     ax, Quadrant_Ofs
  327.                 mov     si, offset ScreenSave
  328.                 add     si, ax
  329.                 add     di, ax
  330.                 mov     cx, 250
  331.         repe    cmpsw
  332.                 jne     I8_SaveScreen
  333.  
  334.                 inc     QuadrantCounter
  335.                 cmp     QuadrantCounter, 8
  336.                 je      ChkShape
  337.                 jmp     I8_ChkScreen
  338.  
  339. ChkShape:       mov     ax, 0040h
  340.                 mov     es, ax
  341.                 mov     ax, word ptr es:[0060h]
  342.                 cmp     ax, CursorShape
  343.                 jne     I8_SaveScreen
  344.  
  345.                 mov     ax, word ptr es:[0050h]
  346.                 cmp     ax, CursorLoc
  347.                 jne     I8_SaveScreen
  348.  
  349.                 jmp     Int08Exit
  350.  
  351. I8_SaveScreen:  push    cs
  352.                 pop     es
  353.                 mov     ax, Quadrant_Ofs
  354.                 mov     di, offset ScreenSave
  355.                 lds     si, VideoPtr
  356.                 add     si, ax
  357.                 add     di, ax
  358.                 mov     cx, 250
  359.         rep     movsw
  360.                 push    cs
  361.                 pop     ds
  362.  
  363. I8_BldPacket:   mov     ax, Quadrant_Ofs
  364.                 mov     ScreenPos, ax
  365.                 mov     ax, 0040h
  366.                 mov     es, ax
  367.                 mov     ax, word ptr es:[0060h]
  368.                 mov     CursorShape, ax
  369.                 mov     ax, word ptr es:[0050h]
  370.                 mov     CursorLoc, ax
  371.                 mov     ax, word ptr es:[001Ah]
  372.                 mov     Head2, ax
  373.  
  374.                 mov     ax, cs
  375.                 mov     es, ax
  376.                 mov     si, offset ScreenSave
  377.                 add     si, Quadrant_Ofs
  378.                 mov     di, offset ScreenPkt
  379.                 mov     cx, 250
  380.         rep     movsw
  381.  
  382. I8_SendScreen:  mov     dx, cs
  383.                 mov     ax, offset Screen_Data
  384.                 mov     cx, 508
  385.                 mov     bp, 0
  386.                 mov     bx, 0
  387.                 mov     si, offset master_name
  388.                 call    Send_Msg
  389.  
  390. Int08Exit:      mov     InInt8, 0
  391.  
  392. I8_RestoreRegs: pop     es
  393.                 pop     ds
  394.                 pop     bp
  395.                 pop     di
  396.                 pop     si
  397.                 pop     dx
  398.                 pop     cx
  399.                 pop     bx
  400.                 pop     ax
  401.  
  402. I8_Sw_Stack2:   cli
  403.                 mov     ss, cs:SS_Save1
  404.                 mov     sp, cs:SP_Save1
  405.  
  406.                 iret
  407.  
  408.                 Assume  CS:_TEXT, DS:Nothing
  409.  
  410. ;---------------------------------------
  411.  
  412. Kbd_Receive:    mov     cs:SS_Save2, ss
  413.                 mov     cs:SP_Save2, sp
  414.                 mov     ss, cs:StackSeg2
  415.                 mov     sp, cs:StackOfs2
  416.  
  417.                 sti
  418.                 cld
  419.                 push    ax
  420.                 push    bx
  421.                 push    cx
  422.                 push    dx
  423.                 push    si
  424.                 push    di
  425.                 push    bp
  426.                 push    ds
  427.                 push    es
  428.  
  429.                 Assume  CS:_TEXT, DS:_TEXT
  430.                 mov     ax, cs
  431.                 mov     ds, ax
  432.  
  433. Chk_RetCode:    cmp     recv_ncb.CMD_CPLT, 0
  434.                 je      ChkDone
  435.  
  436.                 jmp     KR_RecvKbd
  437.  
  438. ChkDone:        cmp     Sess_Flag, -1
  439.                 je      KR_CloseSess
  440.  
  441.                 cmp     Sess_Flag, 1
  442.                 je      KR_OpenSess
  443.  
  444.                 jmp     KR_StuffBuffer
  445.  
  446. KR_CloseSess:   mov     SessionActive, 0
  447.                 mov     ax, 0040h
  448.                 mov     es, ax
  449.                 cli
  450.                 mov     byte ptr es:[0017h], 0
  451.                 mov     byte ptr es:[0018h], 0
  452.                 mov     ax, word ptr es:[0080h]
  453.                 mov     word ptr es:[001Ah], ax
  454.                 mov     word ptr es:[001Ch], ax
  455.                 sti
  456.                 mov     ax, ds
  457.                 mov     es, ax
  458.                 jmp     KR_RecvKbd
  459.  
  460. KR_OpenSess:    mov     ax, 0040h
  461.                 mov     es, ax
  462.                 cli
  463.                 mov     byte ptr es:[0017h], 0
  464.                 mov     byte ptr es:[0018h], 0
  465.                 mov     ax, word ptr es:[0080h]
  466.                 mov     word ptr es:[001Ah], ax
  467.                 mov     word ptr es:[001Ch], ax
  468.                 sti
  469.                 mov     ax, ds
  470.                 mov     es, ax
  471.  
  472. KR_ResetScrn:   mov     di, offset ScreenSave
  473.                 mov     ax, 0
  474.                 mov     cx, 2000
  475.         rep     stosw
  476.                 mov     CursorShape, 0
  477.                 mov     CursorLoc, 0
  478.  
  479. PingBack:       mov     ScreenPos, -1
  480.                 mov     dx, cs
  481.                 mov     ax, offset Screen_Data
  482.                 mov     cx, 8
  483.                 mov     bp, 0
  484.                 mov     bx, 0
  485.                 mov     si, offset master_name
  486.                 call    Send_Msg
  487.  
  488. KR_WaitCplt:    cmp     send_ncb.CMD_CPLT, 0FFh
  489.                 je      KR_WaitCplt
  490.  
  491.                 mov     SessionActive, 1
  492.                 jmp     KR_RecvKbd
  493.  
  494. KR_StuffBuffer: mov     ax, 0040h
  495.                 mov     es, ax
  496.                 cli
  497.                 mov     al, KbdFlag1
  498.                 mov     byte ptr es:[0017h], al
  499.                 mov     al, KbdFlag2
  500.                 mov     byte ptr es:[0018h], al
  501.                 mov     al, AltInput
  502.                 mov     byte ptr es:[0019h], al
  503.                 mov     ax, Tail
  504.                 mov     word ptr es:[001Ch], ax
  505.                 mov     di, 001Eh
  506.                 mov     si, offset KbdBuffer
  507.                 mov     cx, 16
  508.         rep     movsw
  509.                 sti
  510.  
  511. KR_RecvKbd:     mov     dx, cs
  512.                 mov     ax, offset Kbd_Data
  513.                 mov     cx, 39
  514.                 mov     bp, cs
  515.                 mov     bx, offset Kbd_Receive
  516.                 call    Recv_Msg
  517.  
  518.                 Assume  CS:_TEXT, DS:Nothing
  519. Kbd_Exit:       pop     es
  520.                 pop     ds
  521.                 pop     bp
  522.                 pop     di
  523.                 pop     si
  524.                 pop     dx
  525.                 pop     cx
  526.                 pop     bx
  527.                 pop     ax
  528.  
  529.                 cli
  530.                 mov     ss, cs:SS_Save2
  531.                 mov     sp, cs:SP_Save2
  532.  
  533.                 iret
  534.  
  535. ;---------------------------------------
  536.  
  537. EndResident     Label   Byte
  538.                 DB      0
  539.  
  540. ;---------------------------------------
  541.  
  542. Start:          Assume  CS:_TEXT, DS:_DATA, ES:Nothing
  543.                 mov     ax, @DATA
  544.                 mov     ds, ax
  545.  
  546.                 mov     ax, cs
  547.                 mov     cs:StackSeg1, ax
  548.                 mov     ax, offset OurStack1
  549.                 mov     cs:StackOfs1, ax
  550.  
  551.                 mov     ax, cs
  552.                 mov     cs:StackSeg2, ax
  553.                 mov     ax, offset OurStack2
  554.                 mov     cs:StackOfs2, ax
  555.  
  556. save_int8:      mov     ax, 3508h
  557.                 int     21h
  558.                 mov     cs:oldint08_seg, ES
  559.                 mov     cs:oldint08_ofs, BX
  560.  
  561. get_dos_vers:   mov     ax, 3000h
  562.                 int     21h
  563.                 mov     cs:dos_major, al
  564.                 mov     cs:dos_minor, ah
  565.                 cmp     al, 2
  566.                 ja      netbios_test1
  567.  
  568. wrong_dos:      mov     bx, 2
  569.                 mov     dx, offset Msg2
  570.                 mov     cx, Msg2Len
  571.                 mov     ah, 40h
  572.                 int     21h
  573.  
  574.                 mov     ax, 4C00h
  575.                 int     21h
  576.  
  577. netbios_test1:  mov     ax, 0
  578.                 mov     es, ax
  579.                 cmp     word ptr es:[0170h], 0
  580.                 jne     netbios_test2
  581.  
  582. no_netbios:     mov     bx, 2
  583.                 mov     dx, offset Msg3
  584.                 mov     cx, Msg3Len
  585.                 mov     ah, 40h
  586.                 int     21h
  587.  
  588. prog_exit:      mov     ax, 4C00h
  589.                 int     21h
  590.  
  591. netbios_test2:  mov     cs:send_ncb.COMMAND, 7Fh
  592.                 mov     cs:send_ncb.RETCODE, 0
  593.                 mov     cs:send_ncb.CMD_CPLT, 0FFh
  594.                 mov     ax, cs
  595.                 mov     es, ax
  596.                 mov     bx, offset send_ncb
  597.                 Int     5Ch
  598.                 cmp     cs:send_ncb.RETCODE, 3
  599.                 jne     no_netbios
  600.  
  601. bw_or_color:    mov     ah, 0Fh
  602.                 int     10h
  603.                 Cmp     AL, 7
  604.                 JE      SetMono
  605.                 Jmp     LookFurther
  606.  
  607. SetMono:        Mov     cs:VideoSeg, 0B000h
  608.                 Mov     cs:VideoOfs, 0000
  609.                 Jmp     get_psp
  610.  
  611. LookFurther:    Mov     bx, 0FF10h
  612.                 Mov     ah, 12h
  613.                 Int     10h
  614.                 Test    bh, 0FEh
  615.                 JZ      EGAPresent
  616.                 Jmp     SetCGA
  617.  
  618. EGAPresent:     LES     BX, EGAFlagPtr
  619.                 Mov     AL, Byte Ptr ES:[BX]
  620.                 Test    AL, 00000101b
  621.                 JNZ     SetCGA
  622.                 Test    AL, 00000100b
  623.                 JNZ     SetMono
  624.                 Test    AL, 00000001b
  625.                 JNZ     SetMono
  626.  
  627. EGAIsActive:    Mov     cs:VideoSeg, 0B800h
  628.                 Mov     cs:VideoOfs, 0000
  629.                 Jmp     get_psp
  630.  
  631. SetCGA:         Mov     cs:VideoSeg, 0B800h
  632.                 Mov     cs:VideoOfs, 0000
  633.  
  634. get_psp:        mov     ax, 5100h
  635.                 int     21h
  636.                 mov     cs:our_psp, bx
  637.                 dec     bx
  638.                 mov     cs:our_mcb_seg, bx
  639.  
  640. network_name:   mov     bx, 2
  641.                 mov     dx, offset Msg4
  642.                 mov     cx, Msg4Len
  643.                 mov     ah, 40h
  644.                 int     21h
  645.  
  646.                 call    Add_Our_Name
  647.                 mov     al, cs:add_name_ncb.NUM
  648.                 mov     cs:OurNameNumber, al
  649.                 cmp     cs:add_name_ncb.CMD_CPLT, 0
  650.                 je      install_int8
  651.                 jmp     prog_exit
  652.  
  653. install_int8:   push    ds
  654.                 mov     dx, offset Int_08
  655.                 push    cs
  656.                 pop     ds
  657.                 mov     ax, 2508h
  658.                 int     21h
  659.                 pop     ds
  660.  
  661. say_hello:      mov     bx, 2
  662.                 mov     dx, offset Msg1
  663.                 mov     cx, Msg1Len
  664.                 mov     ah, 40h
  665.                 int     21h
  666.  
  667. First_Recv:     mov     dx, cs
  668.                 mov     ax, offset Kbd_Data
  669.                 mov     cx, 39
  670.                 mov     bp, cs
  671.                 mov     bx, offset Kbd_Receive
  672.                 call    Recv_Msg
  673.  
  674. issue_tsr:      Mov     AX, cs
  675.                 Sub     AX, cs:our_psp
  676.                 Mov     BX, Offset EndResident
  677.                 Mov     CX, 4
  678.                 Shr     BX, CL
  679.                 Inc     BX
  680.                 Add     AX, BX
  681.                 Mov     DX, AX
  682.                 Mov     AH, 31h
  683.                 Int     21h
  684.  
  685.                 End     Start
  686.  
  687.  
  688.